﻿<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
    <title></title>
    <link href="http://sstatic.net/so/all.css" rel="stylesheet" />

    <script src="scripts/Soapi.js" type="text/javascript"></script>

    <style type="text/css">
        body {
            margin-top: 2.5em;
        }
        .separator {
            border-bottom: solid 1px black;
            clear: both;
        }
        .user-info {
            width: 220px;
            float: left;
            margin: 6px;
        }
        #footer {
            background-color: #EEEEEE;
            color: Black;
        }
        .footerdiv {
            margin: 6px;
        }
        .copyright {
            margin-top: 10px;
            color: #3366CC;
        }
        .user-data {
            clear: both;
            margin: 8px;
            padding: 8px;
        }
    </style>

    <script type="text/javascript">

        /************************************************************************************************************************
        * Just in case we are in IE and the user has not loaded
        * firebug lite with the footer link
        */
        if ("undefined" === typeof window.console)
        {
            window.console = {
                "log": function() { }
            };
        };


        function getMoversAndShakers()
        {


            Soapi.RouteFactory("api.stackapps.com", apiKey)
                .Search({ pagesize: 100, tagged: "status-norepro;status-deferred;status-declined;status-bydesign;status-completed;bug;feature-request" })
                .getPagedResponse(function(data)
                {

                    var users = [];
                    // extract the users in this group
                    arrayEach(data.items, function(index, question)
                    {
                        if (question.owner && question.owner.user_id)
                        {
                            if (arrayFind(users, function(value)
                            {
                                return value.user_id == question.owner.user_id;
                            }) == -1)
                            {
                                users.push(question.owner);
                            }

                        };
                    });

                    document.getElementById("content").innerHTML = "<div><h3>All Open Bugs</h3><ul id='open-bugs'></ul></div><div class='separator'></div><div><h3>All Open Features</h3><ul id='open-features'></ul></div><div class='separator'></div>";
                    // for each user, tally tags and score
                    arrayEach(users, function(i, user)
                    {
                        // iterate questions
                        arrayEach(data.items, function(i, question)
                        {
                            // find the weighted tag
                            objectEach(tagWeights, function(key, value)
                            {


                                if (question.owner && question.owner.user_id && question.owner.user_id == user.user_id && indexOf(question.tags, key) > -1)
                                {
                                    // if this is bug/feature request and a status tag is present, disregard, it will be listed under status
                                    if ((key == "bug" || key == "feature-request") && question.tags.join(" ").indexOf("status") > -1)
                                    {
                                        //noop

                                    }
                                    else
                                    {
                                        // update questions and score
                                        user[key] = user[key] || [];
                                        user[key].push(question);
                                        user.score = (user.score || 0) + value;

                                        if (key == "bug" && question.tags.join(" ").indexOf("status") == -1)
                                        {
                                            //noop
                                            document.getElementById("open-bugs").innerHTML += "<li><a href='http://stackapps.com/questions/" + question.question_id + "' target='_blank'>" + question.title + "</a></li>";
                                        }

                                        if (key == "feature-request" && question.tags.join(" ").indexOf("status") == -1)
                                        {
                                            //noop
                                            document.getElementById("open-features").innerHTML += "<li><a href='http://stackapps.com/questions/" + question.question_id + "' target='_blank'>" + question.title + "</a></li>";
                                        }

                                    };


                                };
                            });

                        });
                    });

                    // sort by score desc
                    users = users.sort(function(a, b)
                    {
                        return b.score - a.score;
                    });
                    arrayEach(users, function(i, user)
                    {
                        displayUserData(user);
                    });
                }, null, function(data) { log("fetched page " + data.page + " of " + (Math.floor(data.total / data.pagesize) + 1)); });
        };

        function displayUserData(user)
        {
            var userDiv = document.createElement("div");
            userDiv.innerHTML = "<h2><a href='http://stackapps.com/users/" + user.user_id + "/' target='_blank'>" + user.display_name + "</a> : " + user.score + "</h2>";
            userDiv.className = "user-data";
            document.getElementById("content").appendChild(userDiv);
            // list questions
            objectEach(tagWeights, function(key, value)
            {
                if (user[key])
                {
                    var tagDiv = document.createElement("div");
                    userDiv.appendChild(tagDiv);
                    tagDiv.innerHTML = "<br/><h4>" + tagTitles[key] + " (" + value + " point" + (value > 1 ? "s" : "") + ")</h4><ul>";

                    arrayEach(user[key], function(i, question)
                    {
                        tagDiv.innerHTML += "<li><a href='http://stackapps.com/questions/" + question.question_id + "' target='_blank'>" + question.title + "</a></li>";
                    });
                    tagDiv.innerHTML += "</ul>";
                };
            });

            ///<div class='separator'>&nbsp;</div>
            var sepDiv = document.createElement("div");
            sepDiv.className = "separator";
            sepDiv.innerHTML = "&nbsp;";
            userDiv.appendChild(sepDiv);

        };

        var apiKey = "qgAq_KfDu0KYzlNG-qaTuw";

        var tagWeights = {
            "bug": 1, // recognition for identifying a 'possible' issue
            "feature-request": 1, // recognition for actively participating
            "status-completed": 5, // recognition for identifying a valid issue that was resolved
            "status-deferred": 3, // recognition for identifying a an issue that will be addressed at a later date
            "status-norepro": 1, // recognition for identifying a 'possible' issue
            "status-bydesign": 1, // recognition for actively participating
            "status-declined": 1 // recognition for actively participating
        };
        var tagTitles = {
            "bug": "Open Bugs",
            "feature-request": "Open Features",
            "status-completed": "Resolved Bugs / Implemented Features",
            "status-deferred": "Deferred Bugs/Features",
            "status-norepro": "No Repro Bugs",
            "status-bydesign": "By Design",
            "status-declined": "Rejected Bugs/Features"
        };

        function arrayEach(array, callback)
        {
            for (var i = 0; i < array.length; i++)
            {
                callback(i, array[i]);
            }
        };

        function objectEach(object, callback)
        {
            for (var key in object)
            {
                if (object.hasOwnProperty(key))
                {
                    callback(key, object[key]);
                };
            };
        };

        function arrayFind(array, selector)
        {
            for (var i = 0; i < array.length; i++)
            {
                if (selector(array[i]))
                {
                    return i;
                };
            }
            return -1;
        };

        function indexOf(array, value)
        {
            for (var i = 0; i < array.length; i++)
            {
                if (array[i] == value)
                {
                    return i;
                };
            }
            return -1;
        };
        function log(message)
        {
            document.getElementById("content").innerHTML = "<br/><strong>" + message + "</strong>";
        };
    </script>

</head>
<body onload="getMoversAndShakers()">
    <div class="container">
        <h1>
            StackApps Bugs and Features - Present and Past</h1>
        <div class='separator'>
            &nbsp;</div>
        <div id="content">
            Working....
        </div>
        <div id="footer">
            <div class="footerdiv">
                View log in <a href="javascript:(function(F,i,r,e,b,u,g,L,I,T,E){if(F.getElementById(b))return;E=F[i+'NS']&amp;&amp;F.documentElement.namespaceURI;E=E?F[i+'NS'](E,'script'):F[i]('script');E[r]('id',b);E[r]('src',I+g+T);E[r](b,u);(F[e]('head')[0]||F[e]('body')[0]).appendChild(E);E=new%20Image;E[r]('src',I+L);})(document,'createElement','setAttribute','getElementsByTagName','FirebugLite','4','firebug-lite.js','releases/lite/latest/skin/xp/sprite.png','https://getfirebug.com/','#startOpened');">
                    Firebug Lite</a></div>
            <div class="footerdiv">
                This applet was built using only <a href="http://stackapps.com/questions/494" target="_blank">
                    SOAPI.JS</a>, an intuitive JavaScript wrapper library for the <a href="http://stackapps.com/questions/2/getting-started-with-the-api"
                        target="_blank">Stack Overflow API</a><br />
            </div>
            <div class="footerdiv">
                No jQuery scripts where harmed in the making of this applet.</div>
            <div class="copyright">
                &copy; 2010 Sky Sanders - Soapi.js is licensed under GPL version 2 open source license.</div>
        </div>
    </div>
</body>
</html>
